/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.rbac.rpc.syncUser.user;

import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.result.BaseRespResult;
import com.je.common.base.service.CommonService;
import com.je.common.base.service.MetaService;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.rbac.exception.CompanyException;
import com.je.rbac.model.syncdata.SyncCompany;
import com.je.rbac.rpc.SyncCompanyDataRpcService;
import com.je.rbac.rpc.syncUser.util.StreamEx;
import com.je.rbac.rpc.syncUser.util.SyncParserUserUtil;
import com.je.rbac.service.IconType;
import com.je.rbac.service.company.RbacCompanyService;
import com.je.rbac.service.remove.CompanyDeptMoveService;
import org.apache.servicecomb.provider.pojo.RpcSchema;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

@RpcSchema(schemaId = "syncCompanyDataRpcService")
public class SyncCompanyDataRpcServiceImpl implements SyncCompanyDataRpcService {

    @Autowired
    private CompanyDeptMoveService companyDeptMoveService;
    @Autowired
    private RbacCompanyService rbacCompanyService;
    @Autowired
    private MetaService metaService;
    @Autowired
    private CommonService commonService;

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public BaseRespResult syncCompanyData(List<SyncCompany> companyData) {
        //拿到所有公司数据（集团，公司）先插入集团数据，然后递归插入子节点数据
        try {
            if(companyData == null || companyData.size()==0){
                return BaseRespResult.errorResult("公司数据为空，请检查！");
            }
            if(StreamEx.checkCFNumByCompanyId(companyData)>0){
                return BaseRespResult.errorResult("JE_RBAC_COMPANY_ID 主键字段重复，请检查！");
            }
            for(SyncCompany eachSyncBean : companyData){
                if(Strings.isNullOrEmpty(eachSyncBean.getSyParent())){
                    return BaseRespResult.errorResult("SY_PARENT 字段不允许为空，请检查！");
                }
                if("ROOT".equals(eachSyncBean.getSyParent())){
                    DynaBean eachBean = SyncParserUserUtil.buildCompanyBean(eachSyncBean);
                    if(!rbacCompanyService.checkCompanyNameUnique(eachBean)){
                        return BaseRespResult.errorResult("公司名称重复，请修改！");
                    }
                    if(!rbacCompanyService.checkCompanyCodeUnique(eachBean)){
                        return BaseRespResult.errorResult("公司编码重复，请修改！");
                    }
                    DynaBean bean = metaService.selectOne("JE_RBAC_COMPANY",ConditionsWrapper.builder().eq("JE_RBAC_COMPANY_ID",eachBean.getStr("JE_RBAC_COMPANY_ID")));
                    if(bean == null){
                        buildGroupCompanyBeanTreeInfo(eachBean);
                        metaService.insert(eachBean);
                    }else{
                        //此处如果数据已经存在，则放在处理层级逻辑中，更新基本数据；方便对比层级变化。
                    }
                    //递归处理子节点
                    recursiveUpdateComPanyInfo(eachBean,eachSyncBean.getChildList());
                }
            }
            //处理层级逻辑
            processLevel(companyData);
        } catch (Exception e) {
            return BaseRespResult.errorResult(e.getMessage());
        }
        return BaseRespResult.successResult("操作成功！");
    }

    /***
     * 处理层级
     * @param companyData
     * @throws Exception
     */
    public void processLevel(List<SyncCompany> companyData) throws Exception{
        for(SyncCompany eachSyncBean : companyData){
            if("ROOT".equals(eachSyncBean.getSyParent())) {
                DynaBean eachBean = SyncParserUserUtil.buildCompanyBean(eachSyncBean);
                DynaBean sourceBean = metaService.selectOne("JE_RBAC_COMPANY",ConditionsWrapper.builder().eq("JE_RBAC_COMPANY_ID",eachBean.getStr("JE_RBAC_COMPANY_ID")));
                if(sourceBean != null){
                    if(!sourceBean.getStr("SY_PARENT").equals(eachBean.getStr("SY_PARENT")) ){
                        //------------处理数据层级--------------------
                        //循环查找层级变化的数据，先判断层级是否符合规则，不符合则全部回滚; 若符合则调用move方法：移动到目标公司内部
                        checkCompanyLevel(sourceBean,eachBean);
                        DynaBean dynaBean = new DynaBean("JE_RBAC_COMPANY",false);
                        dynaBean.put("id",sourceBean.getStr("JE_RBAC_COMPANY_ID"));
                        dynaBean.put("toId",eachBean.getStr("SY_PARENT"));
                        dynaBean.put("place","inside");
                        companyDeptMoveService.move(dynaBean);
                    }
                    //更新基本信息
                    metaService.update(eachBean);
                }
                //递归处理子节点
                recursiveProcessLevelInfo(eachBean,eachSyncBean.getChildList());
            }
        }
    }

    @Transactional(rollbackFor = {Exception.class})
    public void recursiveProcessLevelInfo(DynaBean parentBean,List<SyncCompany> syncChildList) throws Exception {
        if(syncChildList ==null || syncChildList.size()==0){
            return;
        }
        for(SyncCompany eachSyncBean : syncChildList){
            DynaBean eachBean = SyncParserUserUtil.buildCompanyBean(eachSyncBean);
            if(!parentBean.getStr("JE_RBAC_COMPANY_ID").equals(eachBean.getStr("SY_PARENT"))){
                continue;
            }
            DynaBean sourceBean = metaService.selectOne("JE_RBAC_COMPANY",ConditionsWrapper.builder().eq("JE_RBAC_COMPANY_ID",eachBean.getStr("JE_RBAC_COMPANY_ID")));
            if(sourceBean != null ){
                if(!sourceBean.getStr("SY_PARENT").equals(eachBean.getStr("SY_PARENT")) ){
                    //------------处理数据层级--------------------
                    //循环查找层级变化的数据，先判断层级是否符合规则，不符合则全部回滚; 若符合则调用move方法：移动到目标公司内部
                    checkCompanyLevel(sourceBean,eachBean);
                    DynaBean dynaBean = new DynaBean("JE_RBAC_COMPANY",false);
                    dynaBean.put("id",sourceBean.getStr("JE_RBAC_COMPANY_ID"));
                    dynaBean.put("toId",eachBean.getStr("SY_PARENT"));
                    dynaBean.put("place","inside");
                    companyDeptMoveService.move(dynaBean);
                }
                //更新树形数据后，更新基本信息
                metaService.update(eachBean);

            }
            recursiveProcessLevelInfo(eachBean,eachSyncBean.getChildList());
        }
    }

    /***
     * 层级移动校验
     * @param sourceBean
     * @param eachBean
     * @throws CompanyException
     */
    public void checkCompanyLevel(DynaBean sourceBean,DynaBean eachBean) throws CompanyException{
        DynaBean newParentBean = metaService.selectOne("JE_RBAC_COMPANY",ConditionsWrapper.builder().eq("JE_RBAC_COMPANY_ID",eachBean.getStr("SY_PARENT")));
        if("ROOT".equals(sourceBean.getStr("SY_PARENT"))
                && "GROUP_COMPANY".equals(sourceBean.getStr("COMPANY_LEVEL_CODE"))
                && !"ROOT".equals(eachBean.getStr("SY_PARENT"))){
            throw new CompanyException("当前数据: "+eachBean.getStr("COMPANY_NAME") +" 一级集团公司不允许拖拽层级！");
        }
        if("COMPANY".equals(newParentBean.getStr("COMPANY_LEVEL_CODE"))){
            throw new CompanyException("当前数据: "+eachBean.getStr("COMPANY_NAME") +",上级不能为是公司！");
        }
    }


    @Transactional(rollbackFor = {Exception.class})
    public void recursiveUpdateComPanyInfo(DynaBean parentBean,List<SyncCompany> syncChildList) throws Exception {
        if(syncChildList ==null || syncChildList.size()==0){
            return;
        }
        for(SyncCompany eachSyncBean : syncChildList){
            DynaBean eachBean = SyncParserUserUtil.buildCompanyBean(eachSyncBean);
            if(!parentBean.getStr("JE_RBAC_COMPANY_ID").equals(eachBean.getStr("SY_PARENT"))){
                continue;
            }
            if(!rbacCompanyService.checkCompanyNameUnique(eachBean)){
                throw new CompanyException("公司名称重复，请修改！");
            }
            if(!rbacCompanyService.checkCompanyCodeUnique(eachBean)){
                throw new CompanyException("公司编码重复，请修改！");
            }
            DynaBean bean = metaService.selectOne("JE_RBAC_COMPANY",ConditionsWrapper.builder().eq("JE_RBAC_COMPANY_ID",eachBean.getStr("JE_RBAC_COMPANY_ID")));
            if(bean == null){
                buildCompanyBeanTreeInfo(eachBean);
                metaService.insert(eachBean);
            }else{
                //此处如果数据已经存在，则放在处理层级逻辑中，更新基本数据；方便对比层级变化。
            }
            recursiveUpdateComPanyInfo(eachBean,eachSyncBean.getChildList());
        }
    }

    /***
     *构建公司树形信息
     * @param dynaBean
     */
    public void buildCompanyBeanTreeInfo(DynaBean dynaBean){
        String sysParent = Strings.isNullOrEmpty(dynaBean.getStr("SY_PARENT"))? "ROOT" : dynaBean.getStr("SY_PARENT");
        int currentChildCount = 0;
        List<Map<String,Object>> currentChildList = metaService.selectSql("SELECT MAX(SY_ORDERINDEX) AS MAX_COUNT FROM JE_RBAC_VCOMPANYDEPT WHERE SY_PARENT = {0}",sysParent);
        if(currentChildList.size()>0){
            currentChildCount = (int) currentChildList.get(0).get("MAX_COUNT");
        }

        DynaBean parentBean = metaService.selectOne("JE_RBAC_COMPANY", ConditionsWrapper.builder().eq("JE_RBAC_COMPANY_ID", dynaBean.getStr("SY_PARENT")));
        if(parentBean == null){
            throw new CompanyException("不存在的父级公司，请确认父级公司存在！");
        }else{
            if(Strings.isNullOrEmpty(dynaBean.getStr("COMPANY_LEVEL_CODE"))){
                throw new CompanyException("公司级别参数设置有误！");
            }
            if(!dynaBean.getStr("COMPANY_LEVEL_CODE").equals("GROUP_COMPANY") && !dynaBean.getStr("COMPANY_LEVEL_CODE").equals("COMPANY")){
                throw new CompanyException("公司级别参数设置有误！");
            }
            //若父级为公司，该公司级别不能为集团公司
            if(parentBean.getStr("COMPANY_LEVEL_CODE").equals("COMPANY") && dynaBean.getStr("COMPANY_LEVEL_CODE").equals("GROUP_COMPANY")){
                throw new CompanyException("公司级别下无法创建集团公司！");
            }
            //若父级为公司，该公司级别不能为公司
            if(parentBean.getStr("COMPANY_LEVEL_CODE").equals("COMPANY") && dynaBean.getStr("COMPANY_LEVEL_CODE").equals("COMPANY")){
                throw new CompanyException("公司级别下无法创建公司！");
            }
            if(dynaBean.getStr("COMPANY_LEVEL_CODE").equals("COMPANY")){
                dynaBean.set("COMPANY_ICON", IconType.TCONTYPE_COMPANY.getVal());
            }else{
                dynaBean.set("COMPANY_ICON", IconType.TCONTYPE_GROUP.getVal());
            }
            metaService.executeSql("UPDATE JE_RBAC_COMPANY SET SY_NODETYPE='GENERAL' WHERE JE_RBAC_COMPANY_ID = {0}", parentBean.getStr("JE_RBAC_COMPANY_ID"));

            //设置公司数据
            dynaBean.setStr("SY_GROUP_COMPANY_ID",parentBean.getStr("JE_RBAC_COMPANY_ID"));
            dynaBean.setStr("SY_GROUP_COMPANY_NAME",parentBean.getStr("COMPANY_NAME"));

            dynaBean.set("SY_PARENT", parentBean.getStr("JE_RBAC_COMPANY_ID"));
            dynaBean.set("SY_PARENTPATH", parentBean.getStr("SY_PATH"));
            dynaBean.set("SY_LAYER", parentBean.getInt("SY_LAYER") + 1);
            dynaBean.set("SY_NODETYPE", "LEAF");
            dynaBean.set("SY_PATH", parentBean.getStr("SY_PATH") + "/" + dynaBean.getStr("JE_RBAC_COMPANY_ID"));
            dynaBean.set("SY_TREEORDERINDEX", parentBean.getStr("SY_TREEORDERINDEX") + String.format("%06d", currentChildCount+1));
            dynaBean.set("SY_ORDERINDEX",currentChildCount+1);
            dynaBean.set("SY_STATUS", "1");
            commonService.buildModelCreateInfo(dynaBean);
        }
    }

    /***
     *构建集团树形信息
     * @param dynaBean
     */
    public void buildGroupCompanyBeanTreeInfo(DynaBean dynaBean){
        String sysParent = Strings.isNullOrEmpty(dynaBean.getStr("SY_PARENT"))? "ROOT" : dynaBean.getStr("SY_PARENT");
        int currentChildCount = 0;
        List<Map<String,Object>> currentChildList = metaService.selectSql("SELECT MAX(SY_ORDERINDEX) AS MAX_COUNT FROM JE_RBAC_VCOMPANYDEPT WHERE SY_PARENT = {0}",sysParent);
        if(currentChildList.size()>0){
            currentChildCount = (int) currentChildList.get(0).get("MAX_COUNT");
        }
        dynaBean.setStr("SY_GROUP_COMPANY_ID","ROOT");
        dynaBean.setStr("SY_GROUP_COMPANY_NAME","");
        //为空则为顶级集团公司节点
        String path = "/ROOT/" + dynaBean.getStr("JE_RBAC_COMPANY_ID");
        String  treeOderIndex= "000001" + String.format("%06d", currentChildCount+1);
        String icon = IconType.TCONTYPE_GROUP.getVal();
        if(dynaBean.getStr("COMPANY_LEVEL_CODE").equals("COMPANY")){
            icon = IconType.TCONTYPE_COMPANY.getVal();
        }
        dynaBean = buildCompanyTreeNodeModel(dynaBean,"ROOT","/ROOT","1","LEAF",path,treeOderIndex,icon);
        dynaBean.set("SY_ORDERINDEX",currentChildCount+1);
        dynaBean.set("SY_STATUS", "1");
        commonService.buildModelCreateInfo(dynaBean);
    }



    public DynaBean buildCompanyTreeNodeModel(DynaBean dynaBean ,String parent , String parentPath, String layey , String nodetype , String path , String treeOderIndex , String icon){
        dynaBean.set("SY_PARENT", parent);
        dynaBean.set("SY_PARENTPATH", parentPath);
        dynaBean.set("SY_LAYER", layey);
        dynaBean.set("SY_NODETYPE", nodetype);
        dynaBean.set("SY_PATH", path);
        dynaBean.set("SY_TREEORDERINDEX", treeOderIndex);
        dynaBean.set("COMPANY_ICON", icon);
        return dynaBean;
    }

}
